#ifndef _INCLUDED_ASW_CAMPAIGN_SAVE_H
#define _INCLUDED_ASW_CAMPAIGN_SAVE_H
#ifdef _WIN32
#pragma once
#endif

#include "asw_shareddefs.h"
#include "asw_marine_skills.h"

class CASW_Player;
class CASW_Campaign_Info;

// This class describes the state of the current campaign game.  This is what gets saved when the players save their game.
//   When a savegame is loaded in, it is networked to all the clients (so they can bring up the campaign map, etc)

class CASW_Campaign_Save : public CBaseEntity
{
public:
	DECLARE_CLASS( CASW_Campaign_Save, CBaseEntity );
	DECLARE_SERVERCLASS();
	DECLARE_DATADESC();

	CASW_Campaign_Save();
	~CASW_Campaign_Save();

	// savegame version
	int m_iVersion;

	int m_iLowestSkillLevelPlayed;	

	// the campaign this save game is meant for
	CNetworkString( m_CampaignName, 255 );

	// the mission ID of the location the squad is current in
	CNetworkVar(int, m_iCurrentPosition);

	// how many missions are complete in this save
	CNetworkVar(int, m_iNumMissionsComplete);	
	int m_iInitialNumMissionsComplete;	// number of missions complete when this save was created
	
	// how many deaths occured in the playing of the campaign so far
	CNetworkVar(int, m_iNumDeaths);	

	// a list of IDs describing the missions the squad has completed so far
	CNetworkArray(int, m_MissionComplete, ASW_MAX_MISSIONS_PER_CAMPAIGN);	

	CNetworkArray(int, m_NumRetries, ASW_MAX_MISSIONS_PER_CAMPAIGN);

	// voting for next mission to play in a campaign
	CNetworkVar(float, m_fVoteEndTime);
	bool m_bNextMissionVoteEnded;
	CNetworkArray(int, m_NumVotes, ASW_MAX_MISSIONS_PER_CAMPAIGN);	// number of votes each mission has
	
	// data specific to each marine that needs to be saved
	// rpg stats aren't networked in the save, but are networked in the game resource (since non-campaign games need rpg stats too)
	int m_iMarineSkill[ASW_NUM_MARINE_PROFILES][ASW_NUM_SKILL_SLOTS];

	int m_iParasitesKilled[ASW_NUM_MARINE_PROFILES];

	bool UsingFixedSkillPoints() { return m_bFixedSkillPoints.Get(); }
	CNetworkVar(bool, m_bFixedSkillPoints);

	CNetworkArray(bool, m_bMarineWounded, ASW_NUM_MARINE_PROFILES);
	CNetworkArray(bool, m_bMarineDead, ASW_NUM_MARINE_PROFILES);

	// store the marine skills from the end of the last map, so the players can undo if they want
	int m_iPreviousMarineSkill[ASW_NUM_MARINE_PROFILES][ASW_NUM_SKILL_SLOTS];

	// history
	CNetworkArray(string_t, m_MissionsCompleteNames, ASW_NUM_MARINE_PROFILES);	// a string of mission names this marine has participated in
	CNetworkArray(string_t, m_Medals, ASW_NUM_MARINE_PROFILES);				// a string listing which medals this marine has (would be better as ints?)
	
	// single or multiplayer game
	CNetworkVar(bool, m_bMultiplayerGame);

	// date/time
	CNetworkString( m_DateTime, 255 );

	// store Steam IDs and names of each player that has taken part in this save game
	int m_iNumPlayers;

	CUtlVector<string_t> m_PlayerIDs;
	CUtlVector<string_t> m_PlayerNames;

	string_t m_LastCommanders[ ASW_NUM_MARINE_PROFILES ];	// player name + network ID combo of commanders who used these marines last
	int	m_LastMarineResourceSlot[ ASW_NUM_MARINE_PROFILES ];		// MR last occupied by this profile.  Used for preserving order with autoselection.

	// todo:  any extra data, such as optional objectives complete, fancy stuff unlocked?

	// reads in a savegame from keyfiles
	bool LoadGameFromFile(const char *szFileName);	

	// converts savegame to keyfiles and writes it out the savegame folder
	bool SaveGameToFile(const char *szFileName = NULL);

	// updates which steamID owns which selected marine
	void UpdateLastCommanders();

	// altering the game state
	void SetMissionComplete(int iMission);
	void MoveTo(int iMission);

	// doing a long move
	void SetMoveDestination(int iMission);
	void MoveThink();
	int m_iMoveDestination;

	// creates a new savegame at the start of the campaign
	static bool CreateNewSaveGame(char *szFileName, int iFileNameMaxLen, const char *szCampaignName, bool bMultiplayer, const char *szStartingMission);		// szFileName arg is the desired filename or NULL for an autogenerated one.  Function sets szFileName with the filename used.

	// output the contents of the save game to the console for debugging
	void DebugInfo();

	const char* GetCampaignName();

	// boost a marine's skill up by 1 point
	void IncreaseMarineSkill(int nProfileIndex, int nSkillSlot);
	void ReduceMarineSkill(int nProfileIndex, int nSkillSlot);
	void ReviveMarine(int nProfileIndex);

	void IncreaseRetries();
	int GetRetries();

	void AddParasitesKilled(int nProfileIndex, int iParasitesKilled);
	int GetParasitesKilled(int nProfileIndex);

	// wounding
	void SetMarineWounded(int nProfileIndex, bool bWounded);
	bool IsMarineWounded(int nProfileIndex);

	// death
	void SetMarineDead(int nProfileIndex, bool bDead);
	bool IsMarineAlive(int nProfileIndex);

	// reverts one marine's skills to his undo state
	void RevertSkillsToUndoState(int nProfileIndex);

	// copies the current skill values over into the undo array
	void UpdateSkillUndoState();

	// helper functions for examining the campaign save state
	bool IsMissionLinkedToACompleteMission(int i, CASW_Campaign_Info* pCampaignInfo);

	void SelectDefaultNextCampaignMission();

	string_t m_CurrentSaveFileName;

	virtual int				ShouldTransmit( const CCheckTransmitInfo *pInfo );	

	// route building
	struct campaign_route_node_t
	{
		int iMission;
		int iParentMission;
		float f;	//  ( = g + h )
		float g;	// cost from starting point to here, following generated path
		float h;	// estimate of cost to destination
	};
	bool BuildCampaignRoute(int iStart, int iEnd);
	float EstimateCost(CASW_Campaign_Info *pCI, int iStart, int iEnd);
	void DebugBuiltRoute();
	CASW_Campaign_Save::campaign_route_node_t* FindMissionInClosedList(int iMission);
	int m_iRouteDest;
	int m_iRouteStart;
	CUtlVector<campaign_route_node_t> m_ClosedList;
	CUtlVector<campaign_route_node_t> m_OpenList;

	void StartingCampaignVote();	// clears ready flags on players and sets up vote counts
	void ForceNextMissionLaunch();	// forces the vote to end in 10 seconds
	void VoteEndThink();
	void VoteEnded();
	void PlayerVote(CASW_Player* pPlayer, int iMission);
	void PlayerSpectating(CASW_Player* pPlayer);
	// notification of a player disconnecting (used to clear his next campaign map vote, if any)
	void PlayerDisconnected(CASW_Player *pPlayer);
	void OnMarineKilled();
};

// Swarm savegames are stored on the server.  In a singleplayer game this is your machine.  In multiplayer
//  this means if you save a campaign, you'll have to go back to the same server to continue that game.

//  A possible solution to this is to allow download/uploading of savegames, so a user could transparently keep a
//  copy of each savegame on his local machine and possibly upload that to the server if the server doesn't have it.
//  Would need some kind of random GUID to differentiate saves?  And time/date so the player doesn't upload an older save.
//  And this would obviously make multiplayer savegames completely insecure (i.e. one player could upload a haxed savegame
//		with his marine having uber stats).


// used by the campaign init vars (which get set by the new campaign, load game functions, so the
//   server knows what to do campaign wise when the map starts up)
enum asw_campaign_init_t
{
	CAMPAIGN_INIT_SINGLE_MISSION,
	CAMPAIGN_INIT_NEW_CAMPAIGN,
	CAMPAIGN_INIT_LOAD_SAVED
};

#endif // _INCLUDED_ASW_CAMPAIGN_SAVE_H